package com.app.service;

import com.alibaba.fastjson.JSONObject;
import com.app.Timer.RecommendTimer;
import com.app.model.cache.RedisKeys;
import com.app.model.main.Article;
import com.app.model.main.User;
import com.app.model.main.UserInfo;
import com.app.model.response.RecommendArticleResponseBody;
import com.app.model.response.RecommendUserResponseBody;
import com.app.model.response.RetCode;
import com.app.model.response.RetStatus;
import com.app.model.util.CommonFlag;
import com.app.model.util.UserWithScore;
import com.app.repository.interfaces.*;
import com.app.service.utils.RecommendUtil;
import com.app.support.utils.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by Lichaojie on 2017/4/12. It's a beautiful day.
 */
@Service
public class RecommendService {

    private final Logger logger = Logger.getLogger(RecommendService.class);

    @Autowired
    private ResponseService responseService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RecommendUtil recommendUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private ImageMapper imageMapper;
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CommentsOfArticleMapper commentsOfArticleMapper;
    @Autowired
    private ApprovalMapper approvalMapper;
    @Autowired
    private RecommendTimer recommendTimer;



    //用户推荐（加载更多） version_2.0
    public RetStatus getUserRecommendLoadMore(String parameter){

        final long administrator = 37L;

        ObjectMapper objectMapper = new ObjectMapper();
        Map paraMap;
        try{
            paraMap = objectMapper.readValue(parameter,Map.class);
        }catch (IOException e){
            e.printStackTrace();
            return responseService.doResponse(204);
        }

        int userId = (int)paraMap.get("userId");
        int page = (int)paraMap.get("page");
        int number = (int)paraMap.get("number");


        String key1 = RedisKeys.RECOMMEND_USER_LIST + Long.toString(userId);
        if(page == 0){//第一次进入页面
            if(!redisUtil.exists(key1)){//如果没有推荐的数据，此时计算
                recommendTimer.computeSingleRecommend((long)userId);
            }

            String key2 = RedisKeys.RECOMMEND_USER_PAGE_NUMBER + Long.toString(userId);
            if(redisUtil.exists(key2)){
                redisUtil.remove(key2);
            }
            redisUtil.set(key2,-1);
        }

        page = ((Integer)redisUtil.get(RedisKeys.RECOMMEND_USER_PAGE_NUMBER + Long.toString(userId))) + 1;
        logger.info("actual page : " + page);

        List<UserWithScore> list = redisUtil.get(RedisKeys.RECOMMEND_USER_LIST + Long.toString(userId));
        if(list == null){
            return responseService.doResponse(216);
        }else {
            long start = page * number > list.size() ? list.size() : page * number ;
            long end = page * number + number > list.size() ? list.size() : page * number + number ;
            List<RecommendUserResponseBody> userResponseBodyList = new ArrayList<>();
            for (long i = start;i < end; i ++){
                UserWithScore userWithScore = list.get((int)i);
                UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userWithScore.getUserId());
                logger.info("userId : " + userWithScore.getUserId() + "     score : " + userWithScore.getScore());
                RecommendUserResponseBody recommendUserResponseBody = new RecommendUserResponseBody();
                recommendUserResponseBody.setUserId(userInfo.getId())
                        .setNickName(userInfo.getNickName())
                        .setLabel(userInfo.getLabel())
                        .setIntroduction(userInfo.getIntroduction())
                        .setAvator(imageMapper.selectByPrimaryKey(userInfo.getAvator()).getOrigin());

                userResponseBodyList.add(recommendUserResponseBody);
            }

            String key = RedisKeys.RECOMMEND_USER_PAGE_NUMBER + Long.toString(userId);
            if(redisUtil.exists(key)){
                redisUtil.remove(key);
            }
            redisUtil.set(key,page);

            if(userResponseBodyList.size() > 0){
                RetStatus retStatus = new RetStatus();
                retStatus.setCode(100)
                        .setMessage(RetCode.getMessage(100))
                        .setBody(userResponseBodyList);
                return retStatus;
            }else{
                return responseService.doResponse(216);
            }
        }

    }

    //用户推荐（刷新） version_2.0
    public RetStatus getUserRecommendUpdate(String parameter){
        ObjectMapper objectMapper = new ObjectMapper();
        Map paraMap;
        try{
            paraMap = objectMapper.readValue(parameter,Map.class);
        }catch (IOException e){
            e.printStackTrace();
            return responseService.doResponse(204);
        }

        int userId = (int)paraMap.get("userId");
        int page = (int)paraMap.get("page");
        int number = (int)paraMap.get("number");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userId", userId);
        //除了第一次请求时的page=0，之后的page都没有使用，是通过RedisKeys.RECOMMEND_USER_PAGE_NUMBER维护推荐页数的
        jsonObject.put("page", 1);
        jsonObject.put("number", number);

        return getUserRecommendLoadMore(jsonObject.toJSONString());
    }

    //分享贴推荐（加载更多） version_2.0
    public RetStatus getShareRecommendLoadMore(String parameter,byte type){
        ObjectMapper objectMapper = new ObjectMapper();
        Map paraMap;
        try{
            paraMap = objectMapper.readValue(parameter,Map.class);
        }catch (IOException e){
            e.printStackTrace();
            return responseService.doResponse(204);
        }

        int userId = (int)paraMap.get("userId");
        int page = (int)paraMap.get("page");
        int number = (int)paraMap.get("number");


        List<Article> list;
        if(page == 0){
            list = articleMapper.getListOrderedByIdWithoutUserIdDESC(articleMapper.getMaxId() + 1,page,number,type);
            //第一次进入推荐页面，更新两个lastId
            if(list != null && list.size() > 0){
                //更新lastId（加载更多）
                Article article1 = list.get(list.size() - 1);
                long loadMoreLastId = article1.getId();
                String key1 = RedisKeys.RECOMMEND_SHARE_ARTICLE_LOADMORE_LASTID + Integer.toString(userId);
                if(redisUtil.exists(key1)){
                    redisUtil.remove(key1);
                }
                redisUtil.set(key1,loadMoreLastId);

                //更新lastId（刷新）
                Article article2 = list.get(0);
                long updateLastId = article2.getId();
                String key2 = RedisKeys.RECOMMEND_SHARE_ARTICLE_UPDATE_LASTID + Integer.toString(userId);
                if(redisUtil.exists(key2)){
                    redisUtil.remove(key2);
                }
                redisUtil.set(key2,updateLastId);
            }
        }else {
            long lastId = ((Integer)redisUtil.get(RedisKeys.RECOMMEND_SHARE_ARTICLE_LOADMORE_LASTID + Integer.toString(userId))).longValue();
            list = articleMapper.getListOrderedByIdWithoutUserIdDESC(lastId, page, number, type);
            //不是第一次进入推荐页面，此处只更新 加载更多的lastId
            //更新lastId（加载更多）
            if(list != null && list.size() > 0){
                Article article1 = list.get(list.size() - 1);
                long loadMoreLastId = article1.getId();
                String key1 = RedisKeys.RECOMMEND_SHARE_ARTICLE_LOADMORE_LASTID + Integer.toString(userId);
                if(redisUtil.exists(key1)){
                    redisUtil.remove(key1);
                }
                redisUtil.set(key1,loadMoreLastId);
            }
        }

        if(list != null && list.size() > 0){
            List<RecommendArticleResponseBody> recommendArticleResponseBodyList = new ArrayList<>();
            for (Article article : list){
                UserInfo userInfo = userInfoMapper.selectByPrimaryKey(article.getUserId());
                RecommendArticleResponseBody recommendArticleResponseBody = new RecommendArticleResponseBody();
                recommendArticleResponseBody.setUserId(userInfo.getId())
                        .setNickName(userInfo.getNickName())
                        .setLabel(article.getLabel())
                        .setAvator(imageMapper.selectByPrimaryKey(userInfo.getAvator()).getOrigin())
                        .setArticleId(article.getId())
                        .setTitle(article.getTitle())
                        .setContent(article.getContent())
                        .setTime(article.getTime())
                        .setCommentNum(commentsOfArticleMapper.getCommentsNumber(article.getId()))
                        .setApprovalNum(approvalMapper.getApprovalNumber(article.getId(), CommonFlag.ARTICLE))
                        .setImage(article.getImage())
                        .type(article.getType());
                recommendArticleResponseBodyList.add(recommendArticleResponseBody);
            }
            RetStatus retStatus = new RetStatus();
            retStatus.setCode(100)
                    .setMessage(RetCode.getMessage(100))
                    .setBody(recommendArticleResponseBodyList);
            return  retStatus;
        }else {
            return responseService.doResponse(216);
        }

    }

    //分享贴推荐（刷新） version_2.0
    public RetStatus getShareRecommendUpdate(String parameter,byte type){
        ObjectMapper objectMapper = new ObjectMapper();
        Map paraMap;
        try{
            paraMap = objectMapper.readValue(parameter,Map.class);
        }catch (IOException e){
            e.printStackTrace();
            return responseService.doResponse(204);
        }

        int userId = (int)paraMap.get("userId");
        int page = (int)paraMap.get("page");
        int number = (int)paraMap.get("number");

        List<Article> list;
        long lastId = ((Integer)redisUtil.get(RedisKeys.RECOMMEND_SHARE_ARTICLE_UPDATE_LASTID + Integer.toString(userId))).longValue();
        list = articleMapper.getListOrderedByIdWithoutUserIdASC(lastId,page,number,type);

        if(list != null && list.size() > 0){

            //更新lastId（刷新）
            Article article2 = list.get(0);
            long updateLastId = article2.getId();
            String key2 = RedisKeys.RECOMMEND_SHARE_ARTICLE_UPDATE_LASTID + Integer.toString(userId);
            if(redisUtil.exists(key2)){
                redisUtil.remove(key2);
            }
            redisUtil.set(key2,updateLastId);

            List<RecommendArticleResponseBody> recommendArticleResponseBodyList = new ArrayList<>();
            for (Article article : list){
                UserInfo userInfo = userInfoMapper.selectByPrimaryKey(article.getUserId());
                RecommendArticleResponseBody recommendArticleResponseBody = new RecommendArticleResponseBody();
                recommendArticleResponseBody.setUserId(userInfo.getId())
                        .setNickName(userInfo.getNickName())
                        .setLabel(article.getLabel())
                        .setAvator(imageMapper.selectByPrimaryKey(userInfo.getAvator()).getOrigin())
                        .setArticleId(article.getId())
                        .setTitle(article.getTitle())
                        .setContent(article.getContent())
                        .setTime(article.getTime())
                        .setCommentNum(commentsOfArticleMapper.getCommentsNumber(article.getId()))
                        .setApprovalNum(approvalMapper.getApprovalNumber(article.getId(), CommonFlag.ARTICLE))
                        .setImage(article.getImage())
                        .type(article.getType());
                recommendArticleResponseBodyList.add(recommendArticleResponseBody);
            }
            RetStatus retStatus = new RetStatus();
            retStatus.setCode(100)
                    .setMessage(RetCode.getMessage(100))
                    .setBody(recommendArticleResponseBodyList);
            return  retStatus;
        }else {
            return responseService.doResponse(216);
        }

    }

}
